﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using Export2ExcelTest;
using NPOI.SS.UserModel;
using NPOI.XSSF.UserModel;

namespace Export2Excel
{
    public class ExcelImporter
    {
        private XSSFWorkbook _book;

        public ExcelImporter(string path)
        {
            using (FileStream file = new FileStream(path, FileMode.Open, FileAccess.Read))
            {
                _book = new XSSFWorkbook(file);
            }
        }

        public ExcelImporter(Stream stream)
        {
            _book = new XSSFWorkbook(stream);
        }

        public virtual void DataImport<T>(string sheetName, int headerRowIndex, Func<T> preFill, Action<T> postFill)
            where T : new()
        {
            List<ExcelPropertyLocator> mapperCollection = new List<ExcelPropertyLocator>();

            var sheet = _book.GetSheet(sheetName);

            foreach (IRow row in sheet)
            {
                if (row.RowNum < headerRowIndex)
                {
                    continue;
                }
                else if (row.RowNum == headerRowIndex)
                {
                    mapperCollection = GetMapperCollection(row).ToList();
                    continue;
                }

                T model = preFill();

                mapperCollection.ForEach
                    (
                        mapper => mapper.SetValue(row, model)
                    );

                postFill(model);
            }
        }

        protected virtual IEnumerable<ExcelPropertyLocator> GetMapperCollection(IRow row)
        {
            var headerCells = row.Cells.Where(cell => !string.IsNullOrEmpty(cell.StringCellValue));

            IEnumerable<Tuple<PropertyInfo, ColumnNameAttribute>> materials = typeof(FixedAssetInfo).GetProperties()
                .Where
                (
                    p => p.GetCustomAttributes(typeof(ColumnNameAttribute), false).FirstOrDefault() != null
                )
                .Select
                (
                    p => new Tuple<PropertyInfo, ColumnNameAttribute>(
                    item1: p,
                    item2: (ColumnNameAttribute)p.GetCustomAttributes(typeof(ColumnNameAttribute), false).First()
                    )
                );

            IEnumerable<ICell> availableCells = headerCells.Where
                (
                    cell => materials.FirstOrDefault(
                        materia => materia.Item2.ColumnName == cell.StringCellValue) != null
                );

            return availableCells.Select(
                cell => new ExcelPropertyLocator
                {
                    Key = cell.ColumnIndex,
                    PropertyInfo = materials.First(p => p.Item2.ColumnName == cell.StringCellValue).Item1
                }
            );
        }
    }
}
